﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.Drawing.Drawing2D;

namespace FreeWorship
{
	public partial class MainForm : Form
	{
		public Bitmap textBitmap  			= 	null;
		
		private VerseResult verseResult  	=	null;	 	//verse result set
		private Settings settings       	=	null;
		
		private int totalRow				=	0;     		//total rows to show the entire verses
		private int startRow           	=   0;		    //from which row to show in the screen
		private int rowsPerScreen    		=   0;
		
		private int paintRow 				= 	0 ;			//current paint row
		private float paintOffset			= 	0;			//current paint offset
		
		private Font baseFont 				= 	null;		//for calculate font's height and rowsPerScreen, uses verse Font.
		
		bool isBlank 						= 	false;		//blank the screen
		
		private static int WIDTH			=	1024;		//bitmap width
		private static int HEIGHT			=	768;		//bitmap height
		
		private String keyword = null;
		
		private Worship worship = null;
		
		public MainForm()
		{
			InitializeComponent();
			//comboBoxVersion.SelectedIndex=0;
			SetLiveFormScreen();
			
			this.worship = new Worship();
			this.settings= new Settings();
			
			liveForm.Show();
		}
		
		void ComboBoxKeyKeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Enter)
			{
				
				ShowVerses(textBoxKey.Text);
				//comboBoxKey.Items.Clear();
				textBoxKey.Text="";
				textBoxKey.Focus();
				listBoxBook.Hide();
			}else
			{
				
			}
		}
		
		public void UpdatePreview()
		{
			previewPanel.Invalidate();
		}
		
		void ShowVerses(String keyword)
		{
			try{
				verseResult = VerseResult.GetVerseResult(keyword,comboBoxVersion.Text);
				if(verseResult.verseTable.Rows.Count<1)
					throw new NoVerseException();
				
				this.keyword=keyword;
				startRow=0;
				RePaintBitmap();
				UpdatePreview();
				liveForm.updateBitmapAndRepaint(textBitmap);
				UpdateHistory(verseResult.GetTitle());
			}
			catch(MultiBookException)
			{
				//MessageBox.Show("multi book");
			}
			catch(NoBookException)
			{
				//MessageBox.Show("no book");
			}
			catch(KeywordException)
			{
				MessageBox.Show("Please input:<book name> <chapter> <begin verse number> <end verse number>!");
			}
			catch(NoVerseException)
			{
				//MessageBox.Show("no verse");
			}
		}
		
		public void History()
		{
			this.Focus();
			listBoxHistory.Focus();
		}
		
		public void KeyInput()
		{
			this.Focus();
			textBoxKey.Focus();
		}
		
		void UpdateHistory(String title)
		{
			if(! listBoxHistory.Items.Contains(title))
				listBoxHistory.Items.Add(title);
		}

		void ButtonDownClick(object sender, EventArgs e)
		{
			GoDown();
		}
		
		void ButtonHelpClick(object sender, EventArgs e)
		{
			new HelpForm().ShowDialog();
		}
		
		void MainFormKeyDown(object sender, KeyEventArgs e)
		{
			switch(e.KeyCode)
			{
				case Keys.F5:
					GoDown();
					break;
				case Keys.F6:
					GoUp();
					break;
				case Keys.F10:
					GoHome();
					break;
				case Keys.F9:
					GoEnd();
					break;
				case Keys.F7:
					GoPageDown();
					break;
				case Keys.F8:
					GoPageUp();
					break;
				case Keys.F4:
					textBoxKey.Focus();
					break;
				case Keys.F3:
					listBoxHistory.Focus();
					break;
				case Keys.F2:
					Blank();
					break;
			}
		}
		
		
		private void initPaintVariable()
		{
			paintRow=0;
			paintOffset=0;
		}
		
		private int getWordLength(String word,int index)
		{
			for(int i=index;i<word.Length;i++)
				if((word[i]==' ') || (word[i]=='.') || (word[i]==',') || (word[i]==':') || (word[i]=='?'))
					return i-1;
			return -1;
		}
		
		private void DrawString(Graphics g,String paintStr,String fontName,float fontSize,int colorARGB)
			
		{
			float widthFactor=0.73f;
				if(comboBoxVersion.Text=="NIV")
					widthFactor=0.62f;
				
			for(int i=0;i<paintStr.Length;i++)
			{
				if( (paintOffset + g.MeasureString(paintStr[i].ToString(),baseFont).Width*widthFactor*fontSize/settings.verseFontSize) > WIDTH)
				{
					paintRow++;
					paintOffset=0;
				}
				
				if(comboBoxVersion.Text=="NIV")
				{
					
					if((paintStr[i]!=' ')  && (paintStr[i]!='.') && (paintStr[i]!=',') && (paintStr[i]!=':') && (paintStr[i]!='?'))
					{
						int index = getWordLength(paintStr,i);
						if(index>i)
							if( (paintOffset + g.MeasureString("W",baseFont).Width*(index-i+1)*widthFactor*fontSize/settings.verseFontSize) > WIDTH)
						{
							paintRow++;
							paintOffset=0;
						}
					}
				}

				if( (paintRow<0) || ((paintRow>=startRow) && (paintRow<=startRow+rowsPerScreen)))
				{
					Font font=new Font(fontName,fontSize);
					Color color = Color.FromArgb(colorARGB);
					System.Drawing.SolidBrush brush = new System.Drawing.SolidBrush(color);
					if(settings.printTitleAlways)
					{
						if( paintRow<0)
							g.DrawString(paintStr[i].ToString(),font,brush,paintOffset,0 *( baseFont.Height )+settings.topPercentage/100.0f*HEIGHT);
						else
							g.DrawString(paintStr[i].ToString(),font,brush,paintOffset,(paintRow+1-startRow)*( baseFont.Height )+settings.topPercentage/100.0f*HEIGHT);
					}

					else if(paintRow>=0)
						g.DrawString(paintStr[i].ToString(),font,brush,paintOffset,(paintRow-startRow)*( baseFont.Height )+settings.topPercentage/100.0f*HEIGHT);
					
					brush.Dispose();
					font.Dispose();
				}
				
				
				paintOffset +=widthFactor*g.MeasureString(paintStr[i].ToString(),baseFont).Width*fontSize/settings.verseFontSize;
			}
			
			
		}
		
//		private void newLine(bool check)
//		{
//			if((check) && (paintOffset!=0))
//			{
//				paintRow++;
//				paintOffset=0;
//			}
//			else if(paintOffset!=0)
//			{
//				paintRow++;
//				paintOffset=0;
//			}
//		}
		
		private void DrawTitle(Graphics g,String title,bool isEnd)
		{
			if(paintOffset!=0)
			{
				paintRow++;
				paintOffset=0;
			}
			//if(settings.printTitleAlways)
			//	DrawString(g,title,settings.titleFontName,settings.titleFontSize,settings.titleColor,true);
			//else
			DrawString(g,title,settings.titleFontName,settings.titleFontSize,settings.titleColor);
			if(! isEnd)
				if(paintOffset!=0)
			{
				paintRow++;
				paintOffset=0;
			}
		}

		private void DrawVerseNumber(Graphics g,String verseNumber)
		{
			if(settings.newLineEachVerse)
				if(paintOffset!=0)
			{
				paintRow++;
				paintOffset=0;
			}
			
			DrawString(g,verseNumber,settings.verseNumberFontName,settings.verseNumberFontSize,settings.verseNumberColor);
		}
		
		private void DrawVerse(Graphics g,String verse)
		{
			DrawString(g,verse,settings.verseFontName,settings.verseFontSize,settings.verseColor);
		}
		
		public void Blank()
		{
			isBlank = ! isBlank;
			RePaintBitmap();
			//UpdatePreview();
			liveForm.updateBitmapAndRepaint(textBitmap);
		}
		
		public void GoUp()
		{
			if(startRow>0)
			{
				startRow -- ;
				RePaintBitmap();
				UpdatePreview();
				liveForm.updateBitmapAndRepaint(textBitmap);
			}
		}
		
		public void GoDown()
		{
			if(startRow<totalRow)
			{
				startRow ++ ;
				RePaintBitmap();
				UpdatePreview();
				liveForm.updateBitmapAndRepaint(textBitmap);
			}
		}
		
		public void GoHome()
		{
			if(startRow!=0)
			{
				startRow=0;
				RePaintBitmap();
				UpdatePreview();
				liveForm.updateBitmapAndRepaint(textBitmap);
			}
		}
		
		public void GoEnd()
		{
			if(startRow<totalRow-2)
			{
				startRow = totalRow-2;
				RePaintBitmap();
				UpdatePreview();
				liveForm.updateBitmapAndRepaint(textBitmap);
			}
		}
		
		public void GoPageDown()
		{
			if(startRow==totalRow)
				return;
			startRow +=rowsPerScreen ;
			if(startRow>totalRow)
				startRow=totalRow;
			RePaintBitmap();
			UpdatePreview();
			liveForm.updateBitmapAndRepaint(textBitmap);
		}
		
		public void GoPageUp()
		{
			if(startRow==0)
				return;
			startRow -=rowsPerScreen ;
			if(startRow<0)
				startRow=0;
			RePaintBitmap();
			UpdatePreview();
			liveForm.updateBitmapAndRepaint(textBitmap);
		}
		
		public void RePaintBitmap()
		{
			if(textBitmap==null)
			{
				textBitmap=new Bitmap(WIDTH,HEIGHT);
			}
			initPaintVariable();
			
			if(baseFont!=null)
				baseFont.Dispose();
			baseFont=new Font(settings.verseFontName,settings.verseFontSize);
			
			using(Graphics g=Graphics.FromImage(textBitmap))
			{
				if(isBlank)
				{
					g.Clear(Color.Black);
					return;
				}
				else
					g.Clear(Color.FromArgb(settings.backgroundColor));
				
				rowsPerScreen = Convert.ToInt16(this.Height * (100-settings.topPercentage-settings.bottomPercentage)/100.0/baseFont.Height);
				//if (settings.printTitleAtBottom)
				//	rowsPerScreen--;
				if(verseResult!=null)
				{
					if(settings.printTitleAlways)
					{
						settings.printTitleAtTop=false;
						settings.printTitleAtBottom=false;
					}
					
					String title=verseResult.GetTitle();
					
					if(settings.printTitleAtTop)
						DrawTitle(g,title,false);

					DataTable table=verseResult.verseTable;
					for(int j=0;j<table.Rows.Count;j++)
					{
						String verseNumber = Convert.ToString(table.Rows[j][0]);
						String verse = Convert.ToString(table.Rows[j][1]);
						
						DrawVerseNumber(g,verseNumber);
						DrawVerse(g,verse);
					}
					
					if(settings.printTitleAtBottom)
						DrawTitle(g,title,true);
					
					if(settings.printTitleAlways)
					{
						paintRow=-1*paintRow;
						paintOffset=0;
						DrawTitle(g,title,false);
					}
				}
				if(paintRow<0)
					totalRow = -1 * paintRow;
				else
					totalRow = paintRow;
				g.Dispose();
			}
		}
		
		void ComboBoxKeyTextChanged(object sender, EventArgs e)
		{
			String bookName=textBoxKey.Text;
			Object[] bookList = DBUtil.getBookList(bookName.Trim(),comboBoxVersion.Text);
			if(bookList.Length==1)
			{
				listBoxBook.Hide();
				textBoxKey.Text = Convert.ToString(bookList[0])+" ";
				textBoxKey.SelectionStart=textBoxKey.Text.Length;
				//comboBoxKey.set
				
			}
			else if(bookList.Length>1)
			{
				listBoxBook.Items.Clear();
				listBoxBook.Items.AddRange(bookList);
				
				listBoxBook.Show();
			}

		}
		
		void ListBoxBookSelectedIndexChanged(object sender, EventArgs e)
		{
			listBoxBook.Hide();
			textBoxKey.Text =listBoxBook.Items[listBoxBook.SelectedIndex]+" ";
			textBoxKey.SelectionStart=textBoxKey.Text.Length;
		}
	}
}
